Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

Namespace ServiceDiscoveryApplication

    Partial Public Class Form1
        Inherits Form

        Private deviceList As New List(Of C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.Device)()
        Private serviceList As New List(Of C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService)()
        Private connectedServicesList As New List _
                                    (Of C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService)()

        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub cbServiceSearchType_SelectedIndexChanged _
                                    (ByVal sender As Object, ByVal e As EventArgs) _
                                    Handles cbServiceSearchType.SelectedIndexChanged

            If cbServiceSearchType.Text = "Discover all services" Then

                lblServiceTypeText.Visible = False
                cbServiceType.Visible = False

            ElseIf cbServiceSearchType.Text = "Discover by service type" Then

                lblServiceTypeText.Visible = True
                cbServiceType.Visible = True

            End If

        End Sub

        Private Sub lstServices_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) _
        Handles lstServices.SelectedIndexChanged

            If lstServices.SelectedIndex <> -1 Then

                Try
                    Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = _
                                                                                            GetSelectedService()
                    lblServiceName.Text = selectedService.Name
                    lblServiceDesc.Text = selectedService.Description

                    If IsServiceConnected(selectedService) Then

                        btnConnectSync.Enabled = False
                        btnConnectAsync.Enabled = False
                        btnDisconnectAsync.Enabled = True
                        btnDisconnectSync.Enabled = True

                    Else

                        btnConnectSync.Enabled = True
                        btnConnectAsync.Enabled = True
                        btnDisconnectAsync.Enabled = False
                        btnDisconnectSync.Enabled = False

                    End If

                Catch

                    Microsoft.VisualBasic.MsgBox("An unexpected error occured while getting service information.", _
                                                Microsoft.VisualBasic.MsgBoxStyle.Critical, "Service Information")
                    btnConnectSync.Enabled = True
                    btnConnectAsync.Enabled = True
                    btnDisconnectAsync.Enabled = False
                    btnDisconnectSync.Enabled = False

                End Try

            End If

        End Sub

        Private Sub btnSearchService_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles btnSearchService.Click

            Me.Cursor = Cursors.WaitCursor

            Try

                If lstDevices.SelectedIndex = -1 Then
                    Microsoft.VisualBasic.MsgBox("Select a device!")
                    Return
                End If


                If cbServiceSearchType.SelectedIndex = -1 Then
                    Microsoft.VisualBasic.MsgBox("Select a Search Type!")
                    Return
                End If

                If cbServiceSearchType.Text = "Discover by service type" _
                AndAlso cbServiceType.SelectedIndex = -1 Then
                    Microsoft.VisualBasic.MsgBox("Select a Service Type!")
                    Return
                End If

                Dim selectedDevice As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.Device = _
                                                                                    GetSelectedDevice()

                If cbServiceSearchType.Text = "Discover by service type" Then

                    Select Case cbServiceType.Text

                        Case "File Transfer Profile"
                            serviceList = deviceServicesManager1.DiscoverServicesByType _
                                         (selectedDevice, C4F.DevKit.Bluetooth. _
                                          ServiceAndDeviceDiscovery.ServiceType.OBEXFileTransfer)
                            Exit Select

                        Case "Serial Port Profile"
                            serviceList = deviceServicesManager1.DiscoverServicesByType _
                                          (selectedDevice, C4F.DevKit.Bluetooth. _
                                           ServiceAndDeviceDiscovery.ServiceType.SerialPortProfile)
                            Exit Select

                        Case "Object Push Profile"
                            serviceList = deviceServicesManager1.DiscoverServicesByType _
                                          (selectedDevice, C4F.DevKit.Bluetooth. _
                                           ServiceAndDeviceDiscovery.ServiceType.OBEXObjectPush)
                            Exit Select

                    End Select

                Else
                    serviceList = deviceServicesManager1.DiscoverAllServices(selectedDevice)
                End If

                lstServices.Items.Clear()

                If serviceList IsNot Nothing AndAlso serviceList.Count <> 0 Then

                    For Each service As C4F.DevKit.Bluetooth. _
                    ServiceAndDeviceDiscovery.RemoteService In serviceList

                        If Not String.IsNullOrEmpty(service.Name) Then
                            lstServices.Items.Add(service.Name)
                        End If

                    Next

                End If

                If serviceList Is Nothing OrElse serviceList.Count = 0 _
                                          OrElse lstServices.Items.Count = 0 Then
                    Microsoft.VisualBasic.MsgBox("No service was found.", _
                                                 Microsoft.VisualBasic.MsgBoxStyle.Information, _
                                                 "Service Discovery")
                End If

            Catch
                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during service discovery.", _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, "Service Discovery")

            Finally

                btnConnectAsync.Enabled = False
                btnConnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False
                btnDisconnectSync.Enabled = False
                Me.Cursor = Cursors.Default

            End Try

        End Sub

        Private Sub btnSearchDevices_Click(ByVal sender As Object, ByVal e As EventArgs) _
                                                            Handles btnSearchDevices.Click

            ' Discover all devices.
            Try
                InitializeForm()
                Me.Cursor = Cursors.WaitCursor
                deviceList = deviceServicesManager1.DiscoverAllDevices()

                If deviceList IsNot Nothing AndAlso deviceList.Count <> 0 Then
                    For Each device As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.Device In deviceList
                        lstDevices.Items.Add(device.Name)

                    Next

                Else
                    Microsoft.VisualBasic.MsgBox("No device was found.", _
                                                 Microsoft.VisualBasic.MsgBoxStyle.Information, _
                                                 "Device Discovery")

                End If

            Catch
                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during device discovery.", _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, "Device Discovery")


            Finally
                Me.Cursor = Cursors.Default
            End Try

        End Sub

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            btnSearchDevices_Click(sender, e)
        End Sub

        Private Sub InitializeForm()

            lstDevices.Items.Clear()
            lstServices.Items.Clear()
            cbServiceSearchType.SelectedIndex = -1
            cbServiceType.SelectedIndex = -1
            cbServiceSearchType.Enabled = False
            cbServiceType.Enabled = False
            btnSearchService.Enabled = False
            btnConnectSync.Enabled = False
            btnConnectAsync.Enabled = False
            btnDisconnectSync.Enabled = False
            btnDisconnectSync.Enabled = False
            deviceList.Clear()
            serviceList.Clear()
            lblServiceName.Text = String.Empty
            lblServiceDesc.Text = String.Empty

        End Sub

        Private Sub lstDevices_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) _
                                                        Handles lstDevices.SelectedIndexChanged

            If lstDevices.SelectedIndex <> -1 Then

                cbServiceSearchType.Enabled = True
                cbServiceType.Enabled = True
                lstServices.Enabled = True
                btnSearchService.Enabled = True
                lstServices.Items.Clear()
                lblServiceName.Text = String.Empty
                lblServiceDesc.Text = String.Empty
                btnConnectSync.Enabled = False
                btnConnectAsync.Enabled = False
                btnDisconnectSync.Enabled = False
                btnDisconnectSync.Enabled = False
                serviceList.Clear()

            End If

        End Sub

        Private Sub btnConnectSync_Click(ByVal sender As Object, ByVal e As EventArgs) _
                                        Handles btnConnectSync.Click

            Me.Cursor = Cursors.WaitCursor
            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = Nothing
            btnConnectSync.Enabled = False
            btnConnectAsync.Enabled = False

            Try
                selectedService = GetSelectedService()
                RemoveHandler selectedService.Connected, AddressOf selectedService_AsyncConnected
                selectedService.Connect()
                Microsoft.VisualBasic.MsgBox("Synchronous Connection to service " & selectedService.Name & _
                                             " successful!")
                connectedServicesList.Add(selectedService)
                btnDisconnectSync.Enabled = True
                btnDisconnectAsync.Enabled = True

            Catch servEx As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.ServiceConnectionException
                Microsoft.VisualBasic.MsgBox("An error occurred during Synchronous Connection to " _
                                             & selectedService.Name & Environment.NewLine & "Error Details: " & _
                                             servEx.Message, Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Connection")

                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True
                btnDisconnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False

            Catch
                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during Synchronous Connection to " _
                                             & selectedService.Name, Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Connection")
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True
                btnDisconnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False

            Finally
                Me.Cursor = Cursors.Default
            End Try

        End Sub

        Private Sub selectedService_AsyncConnected(ByVal sender As Object, ByVal e As  _
                            C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.ConnectionEventArgs)

            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = _
            TryCast(sender, C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService)

            If selectedService IsNot Nothing AndAlso e.Error Is Nothing Then

                Microsoft.VisualBasic.MsgBox("Asynchronous connection to service " & _
                                             selectedService.Name & " successful!")
                connectedServicesList.Add(selectedService)
                btnDisconnectSync.Enabled = True
                btnDisconnectAsync.Enabled = True

            Else

                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during Asynchronous Connection to " _
                                             & selectedService.Name & Environment.NewLine & _
                                             "Error Details: " & e.Error.Message, _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, "Service Connection")
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True
                btnDisconnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False

            End If

        End Sub

        Private Sub btnConnectAsync_Click(ByVal sender As Object, ByVal e As EventArgs) _
                                                            Handles btnConnectAsync.Click

            Me.Cursor = Cursors.WaitCursor
            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = Nothing
            btnConnectSync.Enabled = False
            btnConnectAsync.Enabled = False

            Try

                selectedService = GetSelectedService()
                RemoveHandler selectedService.Connected, AddressOf selectedService_AsyncConnected
                AddHandler selectedService.Connected, AddressOf selectedService_AsyncConnected
                ' If there is a handler already, remove it and add it again.
                selectedService.ConnectAsync(Guid.NewGuid())

            Catch servEx As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.ServiceConnectionException

                Microsoft.VisualBasic.MsgBox("An error occurred during Asynchronous Connection to " _
                                             & selectedService.Name & Environment.NewLine & _
                                             "Error Details: " & servEx.Message, _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Connection")
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True
                btnDisconnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False

            Catch ex As Exception

                Microsoft.VisualBasic.MsgBox("An unexpected error occurred during Asynchronous" & _
                                             "Connection to " & selectedService.Name & Environment.NewLine & _
                                             "Error Details: " & ex.Message, _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Connection")
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True
                btnDisconnectSync.Enabled = False
                btnDisconnectAsync.Enabled = False

            Finally
                Me.Cursor = Cursors.Default
            End Try

        End Sub

        Private Sub btnDisconnectSync_Click(ByVal sender As Object, ByVal e As EventArgs) _
                                            Handles btnDisconnectSync.Click

            Me.Cursor = Cursors.WaitCursor
            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = Nothing
            btnDisconnectSync.Enabled = False
            btnDisconnectAsync.Enabled = False

            Try

                selectedService = GetSelectedService()
                Dim isConnected As Boolean = IsServiceConnected(selectedService)
                If isConnected Then

                    RemoveHandler selectedService.Disconnected, AddressOf selectedService_AsyncDisconnected
                    selectedService.Disconnect()

                End If

                Microsoft.VisualBasic.MsgBox("Synchronous Disconnection from service " & selectedService.Name & _
                                             " successful!")
                connectedServicesList.Remove(selectedService)
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True

            Catch

                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during" & _
                                             " Synchronous Disonnection to " & selectedService.Name, _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Disconnection")
                btnConnectSync.Enabled = False
                btnConnectAsync.Enabled = False
                btnDisconnectSync.Enabled = True
                btnDisconnectAsync.Enabled = True

            Finally
                Me.Cursor = Cursors.Default
            End Try

        End Sub

        Private Sub selectedService_AsyncDisconnected(ByVal sender As Object, _
                                                    ByVal e As C4F.DevKit.Bluetooth. _
                                                       ServiceAndDeviceDiscovery.DisconnectionEventArgs)

            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = _
            TryCast(sender, C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService)
            If selectedService IsNot Nothing AndAlso e.Error Is Nothing Then

                Microsoft.VisualBasic.MsgBox("Asynchronous disconnection from service " & selectedService.Name & " successful!")
                connectedServicesList.Remove(selectedService)
                btnConnectSync.Enabled = True
                btnConnectAsync.Enabled = True

            Else

                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during Asynchronous " & _
                                             "Disconnection to " & selectedService.Name, _
                                             Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Disconnection")
                btnConnectSync.Enabled = False
                btnConnectAsync.Enabled = False
                btnDisconnectSync.Enabled = True
                btnDisconnectAsync.Enabled = True

            End If

        End Sub

        Private Sub btnDisconnectAsync_Click(ByVal sender As Object, ByVal e As EventArgs) _
                                                                            Handles btnDisconnectAsync.Click

            Me.Cursor = Cursors.WaitCursor
            Dim selectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService = Nothing
            btnDisconnectSync.Enabled = False
            btnDisconnectAsync.Enabled = False

            Try
                selectedService = GetSelectedService()
                Dim isConnected As Boolean = IsServiceConnected(selectedService)

                If isConnected Then
                    RemoveHandler selectedService.Disconnected, AddressOf selectedService_AsyncDisconnected
                    AddHandler selectedService.Disconnected, AddressOf selectedService_AsyncDisconnected
                    ' If there is a handler already, remove it and add it again.
                    selectedService.DisconnectAsync(Guid.NewGuid())
                End If

            Catch

                Microsoft.VisualBasic.MsgBox("An unexpected error was raised during Asynchronous Disconnection to " _
                                             & selectedService.Name, Microsoft.VisualBasic.MsgBoxStyle.Critical, _
                                             "Service Disconnection")
                btnConnectSync.Enabled = False
                btnConnectAsync.Enabled = False
                btnDisconnectSync.Enabled = True
                btnDisconnectAsync.Enabled = True

            Finally
                Me.Cursor = Cursors.Default
            End Try

        End Sub

        Private Function GetSelectedDevice() As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.Device

            For Each device As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.Device In deviceList

                If lstDevices.Items.Contains(device.Name) AndAlso device.Name = lstDevices.Text Then
                    Return device
                End If

            Next

            Throw New Exception("Device could not be found.")
        End Function

        Private Function GetSelectedService() As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService

            For Each service As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService In serviceList

                If lstServices.Items.Contains(service.Name) AndAlso service.Name = lstServices.Text Then
                    Return service
                End If

            Next

            Throw New Exception("Service could not be found.")
        End Function

        Private Function IsServiceConnected(ByRef service As C4F.DevKit.Bluetooth. _
                                             ServiceAndDeviceDiscovery.RemoteService) As Boolean

            For Each connectedService As C4F.DevKit.Bluetooth.ServiceAndDeviceDiscovery.RemoteService In connectedServicesList

                If connectedService.Name = service.Name AndAlso connectedService.Description = service.Description _
                                                        AndAlso connectedService.DeviceAddress.Address = _
                                                        service.DeviceAddress.Address Then
                    service = connectedService
                    Return True
                End If

            Next

            Return False
        End Function

    End Class

End Namespace
